'''
Created on 09/05/2011

@author: Jose Rodriguez Shaw, Sebastian Caredio, Agustin Ventura
'''
import random
import arbol

'''
devuelve una tupla de tipo (nombre variable, valor de verdad)
donde el valor de verdad se pasa por parametro en truthvalue y
y el nombre de la variable se elige aleatoriamente
'''
def genVar(variablesDict, truthValue, seed):
    #genero el generador de numeros aleatorios
    #agrego 10000 a la semilla para que valla variando en cada ejecucion
    seed = seed + 10000
    ranGen = random.Random(seed)
    #genero un numero en el rango de los equivalentes a los numeros asqui del alfabeto
    ranNum = ranGen.randint(97, 122)
    #obtengo la letra equivalente al numero
    ranChar = chr(ranNum)
    #chequeo si la variable ya existe
    #si la variable ya existe, chequeo que su valor de verdad se corresponda
    #con el valor de verdad requerido, sino sigo buscando.
    if variablesDict.has_key(ranChar):
        existingVar = variablesDict[ranChar]
        while (existingVar[1] <> truthValue and variablesDict.has_key(ranChar)):
            seed = seed + 10000
            ranGen = random.Random(seed)
            ranNum = ranGen.randint(97, 122)
            ranChar = chr(ranNum)
            if variablesDict.has_key(ranChar):
                existingVar = variablesDict[ranChar]    
    #si la variable no existe en el diccionario de variables, la agrego                
    if not variablesDict.has_key(ranChar):
        variablesDict[ranChar]=(ranChar, truthValue)                        
    return (ranChar, truthValue)

'''
genera un termino, devuelve un elemento que tiene subarboles
'''
def genTerm(variablesDict, profundidad, truthValue, seed):
    #evaluo si la profundidad es mayor a cero, si no es mayor, entonces quiere decir que
    # no debo seguir entrando en el arbol, por lo que genero una variable.
    if (profundidad <= 0):
        #devuelvo una hoja del arbol conteniendo una variable, el metodo genVar simplemente
        #devuelve una tupla (nombre_variable, valor_de_verdad)
        return arbol.TElemento(genVar(variablesDict, truthValue, seed))
    else:
        #genero el operador
        #genero el generador de numeros aleatorios
        #agrego 10000 a la semilla para que valla variando en cada ejecucion
        seed = seed + 10000
        ranGen = random.Random(seed)
        #genero un numero en el rango de la cantidad de operadores posibles
        ranNum = ranGen.randint(0,3)
        #ranNum=random.randint(0,3)
        #dependiendo del numero, selecciono el operador
        if ranNum == 0:
            oper = 'AND'
        elif ranNum == 1:
            oper = 'OR'
        elif ranNum == 2:
            oper = 'NOT'
        else:
            oper = 'XOR'
        #creo el TElemento que tendra como dato (nodo) al operador y como hijos derecho
        #e izquierdo a sub expresiones tambien generadas por genTerm
        elemento = arbol.TElemento(oper)
        #despues de obtener el operador, tengo que evaluar que valor de verdad pueden
        #tener los terminos a sus costados, dependiendo del valor de verdad de truthvalue
        profundidadSegTerm = profundidad
        if truthValue == 'TRUE':
            if oper == 'AND':      
                elemento.insertar(genTerm(variablesDict, 
                                          profundidad-1, 'TRUE', seed), 'left')
                seed = seed + 10000
                elemento.insertar(genTerm(variablesDict, 
                                          profundidadSegTerm-1, 'TRUE', seed), 'right')
            elif oper == 'OR':
                #genero un numero aleatorio para ver los valores de verdad de los terminos
                ranNum = ranGen.randint(0,1)
                if ranNum == 0:
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidad-1, 'FALSE', seed), 'left')
                    seed = seed + 10000
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidadSegTerm-1, 'TRUE', seed), 'right')
                else:
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidad-1, 'TRUE', seed), 'left')
                    ranNum = ranGen.randint(0,1)
                    seed = seed + 10000
                    if ranNum == 0:
                        elemento.insertar(genTerm(variablesDict, profundidadSegTerm-1, 
                                                  'FALSE', seed), 'right')
                    else:
                        elemento.insertar(genTerm(variablesDict, profundidadSegTerm-1, 
                                                  'TRUE', seed), 'right')
            elif oper == 'XOR':
                #genero un numero aleatorio para ver los valores de verdad de los terminos
                ranNum = ranGen.randint(0,1)
                if ranNum == 0:
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidad-1, 'FALSE', seed), 'left')
                    seed = seed + 10000
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidadSegTerm-1, 'TRUE', seed), 'right')
                else:
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidad-1, 'TRUE', seed), 'left')
                    seed = seed + 10000
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidadSegTerm-1, 'FALSE', seed), 'right')
            elif oper == 'NOT':
                #cuando es un NOT dejo a la derecha en None y solo inserto a la izquierda
                elemento.insertar(genTerm(variablesDict, 
                                          profundidad-1, 'FALSE', seed), 'right')
        elif truthValue == 'FALSE':
            if oper == 'AND':
                #genero un numero aleatorio para ver los valores de verdad de los terminos
                ranNum = ranGen.randint(0,1)
                if ranNum == 1:
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidad-1, 'TRUE', seed), 'left')
                    seed = seed + 10000
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidadSegTerm-1, 'FALSE', seed), 'right')
                else:
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidad-1, 'FALSE', seed), 'left')
                    ranNum = ranGen.randint(0,1)
                    seed = seed + 10000
                    if ranNum == 0:
                        elemento.insertar(genTerm(variablesDict, profundidadSegTerm-1, 
                                                  'FALSE', seed), 'right')
                    else:
                        elemento.insertar(genTerm(variablesDict, profundidadSegTerm-1, 
                                                  'TRUE', seed), 'right')         
            elif oper == 'OR':
                #agrego el parentesis de inicio del termino       
                elemento.insertar(genTerm(variablesDict, 
                                          profundidad-1, 'FALSE', seed), 'left')
                seed = seed + 10000
                elemento.insertar(genTerm(variablesDict, 
                                          profundidadSegTerm-1, 'FALSE', seed), 'right')
            elif oper == 'XOR':
                #genero un numero aleatorio para ver los valores de verdad de los terminos
                ranNum = ranGen.randint(0,1)
                if ranNum == 0:
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidad-1, 'FALSE', seed), 'left')
                    seed = seed + 10000
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidadSegTerm-1, 'FALSE', seed), 'right')
                else:
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidad-1, 'TRUE', seed), 'left')
                    seed = seed + 10000
                    elemento.insertar(genTerm(variablesDict, 
                                              profundidadSegTerm-1, 'TRUE', seed), 'right')
            elif oper == 'NOT':
                elemento.insertar(genTerm(variablesDict, 
                                          profundidad-1, 'TRUE', seed), 'right')
        return elemento

'''
genera una expresion booleana dado un valor de verdad y una profundidad
'''                 
def genExpression(profundidad, truthValue, seed):
    #evaluo si la profundidad es mayor a cero, de lo contrario devuelvo un arbol vacio
    if (profundidad <= 0):
        container = arbol.TArbol()
        return container
    else:
        #este diccionario contendra los nombres de variables que se van creando
        dictVar = {}
        container = arbol.TArbol()
        #inserto la raiz en el arbol, luego el propio metodo genTern ira creando la estructura
        #de subarboles
        container.insertar(genTerm(dictVar, profundidad, truthValue, seed))
        return container